<template>
  <el-form-item :prop="prop" :label="label" :label-width="labelWidth" :size="size">
    <el-radio-group v-model="type" @input="changeType" :style="{marginRight: gutter + 'px'}">
      <el-radio-button :label="dateType[0].type">{{dateType[0].label}}</el-radio-button>
      <el-radio-button :label="dateType[1].type">{{dateType[1].label}}</el-radio-button>
      <el-radio-button v-if="showWeek" :label="dateType[2].type">{{dateType[2].label}}</el-radio-button>
      <el-radio-button v-if="showDay" :label="dateType[3].type">{{dateType[3].label}}</el-radio-button>
    </el-radio-group>
    <el-date-picker
      v-model="date"
      :type="type"
      placeholder="选择日期"
      :clearable="false"
      :format="dateFormat"
      value-format="yyyy-MM-dd HH:mm:ss"
      :picker-options="{firstDayOfWeek: 1}"
      @change="changeDate"
    />
  </el-form-item>
</template>

<script>
/**
 * @description: 日期选择器，可选择年、月、周、日
 * @param {DIC.dateType.value} unitType 日期类型，年、月、周、日
 * @param {Number | String} year 年
 * @param {Number | String} month 月
 * @param {Number | String} week 周
 * @param {Number | String} day 天
 * @param {String} size 尺寸
 * @param {String} prop 表单域 model 字段，在使用 validate、resetFields 方法的情况下，该属性是必填的
 * @param {String} label 标签文本
 * @param {String} labelWidth 表单域标签的的宽度
 * @param {Number} gutter 表单间隔
 * @param {Boolean} showWeek 是否显示周
 * @param {Boolean} showDay 是否显示日
 * @example:
 * <DatePickerWithUnitType
 *  :unitType.sync="unitType"
 *  :year.sync="year"
 *  :month.sync="month"
 *  :week.sync="week"
 *  :day.sync="day"
 * />
 */

import dayjs from 'dayjs'
import weekOfYear from 'dayjs/plugin/weekOfYear'
import "dayjs/locale/zh-cn"
import {DIC} from '@/const/dict'
dayjs.extend(weekOfYear)
dayjs.locale('zh-cn')
export default {
  name: "DatePickerWithUnitType",
  props: {
    unitType: {
      type: [Number, String],
      default: DIC.dateType[0].value
    },
    year: {
      type: [Number, String],
      default: dayjs().year()
    },
    month: {
      type: [Number, String],
      default: dayjs().month() + 1
    },
    week: {
      type: [Number, String],
      default: dayjs().week()
    },
    day: {
      type: [Number, String],
      default: dayjs().date()
    },
    size: {
      type: String,
      default: 'small'
    },
    prop: {
      type: String,
      default: 'unitTypeDate'
    },
    label: {
      type: String,
      default: ''
    },
    labelWidth: {
      type: String,
      default: ''
    },
    gutter: {
      type: Number,
      default: 10
    },
    showWeek: {
      type: Boolean,
      default: true
    },
    showDay: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      type: DIC.dateType[0].type,
      date: dayjs().format("YYYY-MM-DD HH:mm:ss")
    }
  },
  computed: {
    dateType() {return DIC.dateType},
    dateFormat() {
      switch (this.type) {
        case DIC.dateType[0].type: return 'yyyy 年'
        case DIC.dateType[1].type: return 'yyyy 年 MM 月'
        case DIC.dateType[2].type: return 'yyyy 第 WW 周'
        case DIC.dateType[3].type: return 'yyyy 年 MM 月 dd 日'
        default: return 'yyyy 年'
      }
    }
  },
  watch: {
    unitType: {
      handler() {
        this.init()
      },
      immediate: true
    },
    year() {this.init()},
    month() {this.init()},
    week() {this.init()},
    day() {this.init()}
  },
  methods: {
    init() {
      const type = DIC.dateType.find(item => item.value === this.unitType)?.type || DIC.dateType[0].type
      this.type = type
      const unitType = DIC.dateType.find(item => item.type === type)?.value || DIC.dateType[0].value
      this.$emit("update:unitType", unitType)

      const curDate = dayjs()
      switch (type) {
        case DIC.dateType[0].type:
          this.date = dayjs()
            .year(Number.isNaN(Number(this.year)) ? curDate.year() : Number(this.year))
            .format("YYYY-MM-DD HH:mm:ss")
          break
        case DIC.dateType[1].type:
          this.date = dayjs()
            .year(Number.isNaN(Number(this.year)) ? curDate.year() : Number(this.year))
            .month(Number.isNaN(Number(this.month)) ? curDate.month() : Number(this.month) - 1)
            .format("YYYY-MM-DD HH:mm:ss")
          break
        case DIC.dateType[2].type:
          this.date = dayjs()
            .year(Number.isNaN(Number(this.year)) ? curDate.year() : Number(this.year))
            .week(Number.isNaN(Number(this.week)) ? curDate.week() : Number(this.week))
            .format("YYYY-MM-DD HH:mm:ss")
          break
        case DIC.dateType[3].type:
          this.date = dayjs()
            .year(Number.isNaN(Number(this.year)) ? curDate.year() : Number(this.year))
            .month(Number.isNaN(Number(this.month)) ? curDate.month() : Number(this.month) - 1)
            .date(Number.isNaN(Number(this.day)) ? curDate.date() : Number(this.day))
            .format("YYYY-MM-DD HH:mm:ss")
          break
        default:
          break
      }
      this.emitDate()
    },
    changeType(val) {
      const unitType = DIC.dateType.find(item => item.type === val)?.value || DIC.dateType[0].value
      this.$emit("update:unitType", unitType)
      const {year, month, week, day} = this.emitDate()
      this.$emit("changeType", {unitType, year, month, week, day})
    },
    changeDate() {
      const unitType = DIC.dateType.find(item => item.type === this.type)?.value || DIC.dateType[0].value
      const {year, month, week, day} = this.emitDate()
      this.$emit('changeDate', {unitType, year, month, week, day})
    },
    emitDate() {
      const result = {
        year: '',
        month: '',
        week: '',
        day: '',
      }
      switch (this.type) {
        case DIC.dateType[0].type:
          result.year = dayjs(this.date).year()
          break
        case DIC.dateType[1].type:
          result.year = dayjs(this.date).year()
          result.month = dayjs(this.date).month() + 1
          break
        case DIC.dateType[2].type:
          result.year = dayjs(this.date).year()
          result.week = dayjs(this.date).week()
          break
        case DIC.dateType[3].type:
          result.year = dayjs(this.date).year()
          result.month = dayjs(this.date).month() + 1
          result.day = dayjs(this.date).date()
          break
        default:
          result.year = dayjs(this.date).year()
          break
      }
      this.$emit("update:year", result.year)
      this.$emit("update:month", result.month)
      this.$emit("update:week", result.week)
      this.$emit("update:day", result.day)
      return result
    }
  }
}
</script>

<style scoped lang="scss">
::v-deep .el-date-editor{
  position: relative;
}
::v-deep .el-date-picker{
  position: absolute;
  left: 0;
  z-index: 99;
}
</style>
